﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using FlaUI.Core.AutomationElements;
using FlaUI.Core.Definitions;
using FlaUI.UIA3;
using QQTools.Data.Enums.AddGroup;
using QQTools.Data.Repositories;
using QQTools.Utils;
using System.Windows.Forms;
using QQTools.Data.Repositories.AddGroup;
using QQTools.Logging;
using QQTools.Data.Models;
using QQTools.Data.Plus;
using Newtonsoft.Json.Linq;
using System.IO;

namespace QQTools.Services
{

    class AddGroupServices
    {
        /// <summary>
        /// 进度文件路径
        /// </summary>
        private const string AddGroupProgressFilePath = "C:\\QQ怀旧助手配置\\AddGroupProgress.txt";

        private readonly AddGroupRepository _addGroupRepository;
        private readonly QQRepository _qqRepository;
        private readonly AddGroupQQRepository _addGroupQQRepository;
        private readonly MainForm _form;

        public AddGroupServices(MainForm form,
            AddGroupRepository addGroupRepository,
            AddGroupQQRepository addGroupQQRepository,
            QQRepository qqRepository)
        {
            _form = form;
            _addGroupRepository = addGroupRepository;
            _addGroupQQRepository = addGroupQQRepository;
            _qqRepository = qqRepository;
        }


        public async Task Start(List<QQModel> qqList, int addGroupNumber1, int addGroupNumber2, int intervalStart, int intervalEnd, int sleep1, int sleep2, CancellationToken token)
        {
            // 更新状态栏
            _form.UpdateStatusStrip("开始执行加群任务");
            List<AddGroupModel> addGroupInfos = await _addGroupRepository.GetAllAsync();
            // await AddGroupProcess(qq, groupNumber, token);

            // 用来标记有没有加过群, 加过才能休息
            bool flag = false;
            while (!token.IsCancellationRequested)
            {
                // 批次1

                flag = await AddQQsToGroups("批次一", addGroupNumber1, intervalStart, intervalEnd, token, AddGroupQQStatus.Batch1);
                if (token.IsCancellationRequested) break;
                if (flag)
                {
                    // 加过群, 说明批次1结束
                    await _form.StartCountdown($"[批次一结束] 距离开始批次二还剩: ", sleep1 * 60, token, () =>
                    {
                        _form.UpdateStatusStrip("批次一休息结束, 开始批次二");
                    });
                }

                // 批次2
                //if (progress.CurrentBatch == 2) {
                flag = await AddQQsToGroups("批次二", addGroupNumber2, intervalStart, intervalEnd, token, AddGroupQQStatus.Batch2);
                if (token.IsCancellationRequested) break;

                if (flag)
                {
                    // 加过群, 说明批次2结束
                    await _form.StartCountdown($"[批次二结束] 距离开始批次一还剩: ", sleep2 * 60, token, () =>
                    {
                        _form.UpdateStatusStrip("批次二休息结束, 开始批次一");
                    });
                }

            }
            // 删除加群进度文件
            //DeleteProgress();
            LogManager.Info($"加群任务结束, IsCancellationRequested:{token.IsCancellationRequested}");

        }





        public async Task<AddGroupResult> AddGroupProcess(string qq, string groupNumber, CancellationToken cancellationToken)
        {
            try
            {
                LogManager.Info($"[进群任务] 开始加群: QQ={qq}, 群号={groupNumber}");

                // 验证 groupNumber 是否为有效数字
                if (!long.TryParse(groupNumber, out long groupUin))
                {
                    LogManager.Error($"[进群任务] 群号格式错误: {groupNumber}");
                    return AddGroupResult.InvalidGroupNumber;
                }
                // 关闭其他无关窗口
                CloseOtherWindows();
                // 生成腾讯URL并打开浏览器
                string url = QQPlus.GenerateTencentUrl(groupUin: groupUin, qqUin: qq);
                try
                {
                    Process.Start(url);
                }
                catch (Exception ex)
                {
                    LogManager.Error($"[进群任务] 打开浏览器失败: {ex.Message}");
                    return AddGroupResult.BrowserOpenFailed;
                }

                await Task.Delay(1000, cancellationToken);

                AutomationElement addGroupWindow = null;

                // 动态等待群聊窗口加载
                AutomationElement groupChatWindow = null;
                //await WaitForConditionAsync(
                // () => {
                //     addGroupWindow = GetAddGroupWindow();
                //     if (addGroupWindow != null) {
                //         return true;
                //     }
                //     groupChatWindow = QQAuto.GetGroupChatWindow();
                //     return groupChatWindow != null;
                // },
                // TimeSpan.FromSeconds(7));

                //if (groupChatWindow !=null) {
                //    LogManager.Info("[进群任务] 已经在群里");
                //    CloseWindow(groupChatWindow);
                //    return AddGroupResult.Success;
                //}

                // 等待 添加群 窗口加载
                //addGroupWindow = await WaitForWindowAsync(() => GetAddGroupWindow(), TimeSpan.FromSeconds(5), cancellationToken, 3);

                for (int i = 0; i < 10; i++)
                {
                    addGroupWindow = GetAddGroupWindow();
                    if (addGroupWindow != null)
                    {
                        break;
                    }
                    await Task.Delay(500, cancellationToken);
                }

                if (addGroupWindow == null)
                {
                    int processId = QQPlus.GetQQPid(qq);
                    groupChatWindow = await QQPlus.GetGroupChatWindowWin32(processId);
                    if (groupChatWindow != null)
                    {
                        LogManager.Info("[进群任务] 已经在群里");
                        CloseWindow(groupChatWindow);
                        return AddGroupResult.Success;
                    }

                    if (QQPlus.CheckQQIsOffline(qq) == false)
                    {
                        LogManager.Error($"[进群任务]  QQ={qq} 掉线了, 群号={groupUin}");
                        return AddGroupResult.QQOffline;
                    }

                    LogManager.Error($"[进群任务] 寻找:添加群窗口失败 QQ={qq}, 群号={groupUin}");
                    return AddGroupResult.OpenWindowFailed;
                }

                SetForegroundWindow(addGroupWindow);

                //// 检查是否找到群不存在的消息
                //if (FlaUIAuto.FindControl(groupChatWindow, ControlType.Text, "您要查找的群不存在。") != null) {
                //    LogManager.Info($"[进群任务] QQ={qq} 您要查找的群不存在: {groupUin}");
                //    CloseWindow(addGroupWindow);
                //    return AddGroupResult.GroupNotFound;
                //}

                //// 检查是否找到群不存在的消息
                //if (await FindControl(addGroupWindow, "Text", "你正在申请加入家校群", FindMode.Contains, cancellationToken) != null) {
                //    //  if (await FindControl(addGroupWindow, "Text", "你正在申请加入家校群", FindMode.Contains, cancellationToken) != null) {
                //    LogManager.Info($"[进群任务] QQ={qq} 家校群, 无法加入: {groupUin}");
                //    CloseWindow(addGroupWindow);
                //    return AddGroupResult.GroupNotFound;
                //}

                //// 检查是否无法查到该群
                ////if (await CheckMessageExistsAsync(addGroupWindow, "无法查到该群", FindMode.Contains, TimeSpan.FromSeconds(1), cancellationToken, 2)) {
                //if (await FindControl(addGroupWindow, "Text", "无法查到该群", FindMode.Contains, cancellationToken) != null) {
                //    LogManager.Info($"[进群任务] QQ={qq} 无法查到该群: {groupUin}");
                //    CloseWindow(addGroupWindow);
                //    return AddGroupResult.GroupNotFound;
                //}



                // 点击“下一步”按钮
                AutomationElement nextBtn = FlauiAuto.FindControl(addGroupWindow, ControlType.Button, "下一步");
                if (nextBtn != null)
                {
                    nextBtn.Click();
                    LogManager.Info($"[进群任务] 点击:下一步 QQ={qq}, 群号={groupUin}");
                    await Task.Delay(1500, cancellationToken);
                }
                // 检查是出现出错啦的窗口
                IntPtr errorWindow = Win32Api.FindWindow("TXGuiFoundation", "出错啦");
                if (errorWindow != IntPtr.Zero)
                {
                    LogManager.Info($"[进群任务] 窗口:出错啦 QQ={qq}, 群号={groupUin}");
                    Win32Api.CloseAllWindows("TXGuiFoundation", "出错啦");
                    CloseWindow(addGroupWindow);
                    return AddGroupResult.ErrorWindow;
                }

                //// 检查群是否已满员
                //if (await CheckMessageExistsAsync(addGroupWindow, "您要加入的群已经满员", FindMode.Contains, TimeSpan.FromSeconds(1), cancellationToken, 2)) {
                //    LogManager.Info($"[进群任务] 群已满员 QQ={qq}, 群号={groupUin}");
                //    CloseWindow(addGroupWindow);
                //    return AddGroupResult.FullGroup;
                //}


                AutomationElement okBtn = FlauiAuto.FindControl(addGroupWindow, ControlType.Button, "完成");
                // 点击“完成”按钮
                if (okBtn != null)
                {
                    okBtn.Click();
                    LogManager.Info($"[进群任务] 点击:完成 QQ={qq}, 群号={groupUin}");
                    Win32Api.CloseAllWindows("TXGuiFoundation", "添加群");
                    return AddGroupResult.Success;
                }


                AutomationElement closeBtn = FlauiAuto.FindControl(addGroupWindow, ControlType.Button, "关闭");
                if (closeBtn != null)
                {
                    closeBtn.Click();
                    return AddGroupResult.AddFailedWindow;
                }
                AutomationElement chatBtn = FlauiAuto.FindControl(addGroupWindow, ControlType.Button, "进群聊天");
                if (chatBtn != null)
                {
                    LogManager.Info($"[进群任务] 直接进群 QQ={qq}, 群号={groupUin}");
                    CloseWindow(addGroupWindow);
                    return AddGroupResult.Success;
                }

                AutomationElement confirmBtn = FlauiAuto.FindControl(addGroupWindow, ControlType.Button, "确定");
                // 点击“确定”按钮
                if (confirmBtn != null)
                {
                    confirmBtn.Click();
                    LogManager.Info($"[进群任务] 点击:确定 QQ={qq}, 群号={groupUin}");
                    //  Win32Api.CloseAllWindows("TXGuiFoundation", "添加群");
                    return AddGroupResult.AddFailedWindow;
                }

                return AddGroupResult.Unknown;
            }
            catch (OperationCanceledException)
            {
                LogManager.Warn($"[进群任务] 任务被取消 QQ={qq}, 群号={groupNumber}");
                return AddGroupResult.TaskCancelled;
            }
            catch (Exception ex)
            {
                LogManager.Error($"[进群任务] 发生未知错误: {ex.Message}");
                return AddGroupResult.Unknown;
            }
        }


        private async Task<bool> AddQQsToGroups(string batchText, int groupCount, int intervalStart, int intervalEnd, CancellationToken token, AddGroupQQStatus batch)
        {
            string msg = "";
            // 用来记录本次加群的QQ是否已经执行过
            bool flag = false;

            // 从数据库中获取任务列表
            List<AddGroupQQModel> addGroupQQs = await _addGroupQQRepository.GetAllAsync();
            var addGroupQQList = addGroupQQs.ToList();
            // 一:循环所有需要加群的QQ
            foreach (AddGroupQQModel addGroupQQ in addGroupQQs)
            {
                if (token.IsCancellationRequested) break;

                string qq = addGroupQQ.QQ;

                // 从配置记录中获取最后一个加群的QQ
                string lastAddGroupQQ = LoadAddGroupProgress();
                if (string.IsNullOrEmpty(lastAddGroupQQ))
                {
                    // 如果没有记录，则从列表中取第一个QQ
                    lastAddGroupQQ = qq;
                }

                // 需要从上次记录的QQ开始执行任务
                if (lastAddGroupQQ != qq)
                {
                    _form.UpdateStatusStrip($"[加群:跳过] 批次:{batchText} 当前QQ:{qq} 历史记录QQ:{lastAddGroupQQ}");
                    continue;
                }

                // 批次检查
                if (addGroupQQ.CurrentBatch != batch)
                {
                    _form.UpdateStatusStrip($"[加群:跳过] 批次:{batchText} 当前QQ:{qq} 当前:{addGroupQQ.CurrentBatch.ToChineseDString()} 需要:{batch.ToChineseDString()}");
                    continue;
                }

                // 更新UI表格:ListViewAddGroupQQ中 当前 QQ 为进行中
                _form.UpdateListViewAddGroupQQ(addGroupQQ);

                // 记录是不是 QQ 离线 结束
                bool qqOfflineflag = false;
                // 二:循环添加群聊
                for (int i = addGroupQQ.CurrentBatchAddCount; i < groupCount; i++)
                {
                    if (token.IsCancellationRequested) break;

                    try
                    {
                        // 从数据库中获取一个待加群的任务
                        AddGroupModel addGroupInfo = await _addGroupRepository.GetAndLockFirstByStatusAsync();
                        string groupNumber = addGroupInfo.GroupNumber;
                        msg = $"[加群中] {addGroupQQ.CurrentBatch.ToChineseDString()} QQ:{qq} 加群 {groupNumber}  进度:{addGroupQQ.CurrentBatchAddCount}/{groupCount}";
                        LogManager.Info(msg);
                        addGroupInfo.Status = AddGroupStatus.Running;
                        // 更新UI表格:ListViewAddGroup状态为加群中
                        _form.UpdateListViewAddGroup(addGroupInfo);
                        // 更新UI状态栏
                        _form.UpdateStatusStrip(msg);

                        // 调用 AddGroupProcess 方法进行加群
                        AddGroupResult addGroupResult = await AddGroupProcess(qq, groupNumber, token);
                        AddGroupStatus status = AddGroupStatus.Success;

                        // 标记本批次加过群,加过群本批次结束后就需要休息
                        flag = true;

                        switch (addGroupResult)
                        {
                            case AddGroupResult.Success:
                                msg = $"[{addGroupQQ.CurrentBatch.ToChineseDString()}:加群成功]]  QQ:{qq} 加群 {groupNumber}  进度:{addGroupQQ.CurrentBatchAddCount}/{groupCount}";
                                status = AddGroupStatus.Success;
                                break;
                            case AddGroupResult.GroupNotFound:
                                msg = $"[{addGroupQQ.CurrentBatch.ToChineseDString()}:群号错误]] QQ:{qq} 加群 {groupNumber}  进度:{addGroupQQ.CurrentBatchAddCount}/{groupCount}";
                                status = AddGroupStatus.Failed;
                                break;
                            case AddGroupResult.GroupBlockedOrNotAdded:
                                msg = $"[{addGroupQQ.CurrentBatch.ToChineseDString()}:群被封禁或未加群]] QQ:{qq} 加群 {groupNumber}  进度:{addGroupQQ.CurrentBatchAddCount}/{groupCount}";
                                status = AddGroupStatus.Failed;
                                break;
                            case AddGroupResult.OpenWindowFailed:
                                msg = $"[{addGroupQQ.CurrentBatch.ToChineseDString()}:打开群窗口失败]] QQ:{qq} 加群 {groupNumber}  进度:{addGroupQQ.CurrentBatchAddCount}/{groupCount}";
                                status = AddGroupStatus.Failed;
                                break;
                            case AddGroupResult.TaskCancelled:
                                msg = $"[{addGroupQQ.CurrentBatch.ToChineseDString()}:加群任务取消]] QQ:{qq} 加群 {groupNumber}  进度:{addGroupQQ.CurrentBatchAddCount}/{groupCount}";
                                status = AddGroupStatus.Failed;
                                break;
                            case AddGroupResult.ErrorWindow:
                                msg = $"[{addGroupQQ.CurrentBatch.ToChineseDString()}:出现错误窗口]] QQ:{qq} 加群 {groupNumber}  进度:{addGroupQQ.CurrentBatchAddCount}/{groupCount}";
                                status = AddGroupStatus.Failed;
                                break;
                            case AddGroupResult.QQOffline:
                                msg = $"[{addGroupQQ.CurrentBatch.ToChineseDString()}:QQ离线]] QQ:{qq} 加群 {groupNumber}  进度:{addGroupQQ.CurrentBatchAddCount}/{groupCount}";
                                status = AddGroupStatus.Failed;
                                // 标记为离线结束
                                qqOfflineflag = true;
                                break;
                            default:
                                msg = $"[{addGroupQQ.CurrentBatch.ToChineseDString()}:未知错误] ] QQ:{qq} 加群 {groupNumber}  进度:{addGroupQQ.CurrentBatchAddCount}/{groupCount}";
                                status = AddGroupStatus.Failed;
                                break;
                        }

                        // 判断有没有出现QQ离线
                        if (addGroupResult == AddGroupResult.QQOffline)
                        {
                            // 如果QQ离线，则跳出循环
                            // 更新底部状态栏
                            _form.UpdateStatusStrip(msg);
                            // 将 群号状态重置为 待加群, 然后退出这个QQ的 循环
                            await _addGroupRepository.UpdateStatusByGroupNumberAsync(groupNumber, AddGroupStatus.NotStart);

                            break;
                        }

                        // 更新数据库中群号的状态为 status
                        await _addGroupRepository.UpdateStatusByGroupNumberAsync(groupNumber, status);

                        // 当前批次群数加1
                        addGroupQQ.CurrentBatchAddCount++;
                        addGroupQQ.TotalAdd++;
                        // 保存当前QQ的最新进度
                        await _addGroupQQRepository.UpdateAsync(addGroupQQ);

                        // 更新底部状态栏
                        _form.UpdateStatusStrip(msg);
                        // 更新加群记录状态
                        _form.UpdateListViewAddGroup(addGroupInfo);
                        // 更新UI表格:ListViewAddGroupQQ
                        _form.UpdateListViewAddGroupQQ(addGroupQQ);

                    }
                    catch (Exception ex)
                    {
                        // MessageBox.Show($"加群时出错: {ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                        LogManager.Error($"[加群任务] 加群时出错: {ex.Message}");
                    }

                    //if (!addGroupQQ.Equals(addGroupQQList.Last()) && addGroupQQList.Count > 1)
                    //{
                    // 当前元素不是最后一个, 说明需要休息
                    // 随机等待间隔时间
                    int interval = new Random().Next(intervalStart, intervalEnd + 1);
                    msg = $"[{addGroupQQ.CurrentBatch.ToChineseDString()}] QQ:{qq}  进度:{addGroupQQ.CurrentBatchAddCount}/{groupCount}";
                    LogManager.Info($"{msg} 距离下一次加群还剩: {interval} 秒");
                    await _form.StartCountdown($"{msg} 距离下一次加群还剩:", interval, token, $"{msg} 任务停止", null);
                    // }
                }

                if (qqOfflineflag)
                {
                    // 如果因为QQ离线退出的加群，则跳出循环
                    LogManager.Info($"[加群] QQ:{qq} 离线退出加群, 继续下一个QQ");
                }
                else
                {
                    // QQ正常退出，则继续执行
                    // 更新批次状态为已完成
                    if (addGroupQQ.CurrentBatch == AddGroupQQStatus.Batch1)
                    {
                        addGroupQQ.CurrentBatch = AddGroupQQStatus.Batch2;
                    }
                    else
                    {
                        addGroupQQ.CurrentBatch = AddGroupQQStatus.Batch1;
                    }
                    await _addGroupQQRepository.UpdateCurrentBatchAsync(qq, addGroupQQ.CurrentBatch);

                    // 重置批次进度
                    addGroupQQ.CurrentBatchAddCount = 0;
                    await _addGroupQQRepository.ResetCurrentBatchAddCountAsync(qq);
                }
                // 更新QQ列表
                _form.UpdateListViewAddGroupQQ(addGroupQQ);
                // 更新下一个要执行的QQ
                _form.UpdateAddGroupQQProcess(addGroupQQs, addGroupQQ);
            }
            return flag;
        }




        // 封装等待窗口加载逻辑，增加重试机制
        private async Task<AutomationElement> WaitForWindowAsync(Func<AutomationElement> getWindowFunc, TimeSpan timeout, CancellationToken cancellationToken, int retries = 3)
        {
            DateTime deadline = DateTime.Now.Add(timeout);
            for (int attempt = 0; attempt < retries; attempt++)
            {
                if (cancellationToken.IsCancellationRequested)
                {
                    LogManager.Info($"[WaitForWindowAsync] 取消等待窗口: {attempt + 1}/{retries}");
                    return null;
                }

                LogManager.Info($"[WaitForWindowAsync] 尝试等待窗口: {attempt + 1}/{retries}");
                AutomationElement window = getWindowFunc();
                if (window != null)
                {
                    LogManager.Info($"[WaitForWindowAsync] 找到窗口");
                    return window;
                }

                if (DateTime.Now >= deadline)
                {
                    LogManager.Info($"[WaitForWindowAsync] 等待窗口超时");
                    return null;
                }

                await Task.Delay(500, cancellationToken); // 等待500毫秒后重试
            }
            LogManager.Info($"[WaitForWindowAsync] 未找到窗口");
            return null;
        }


        // 根据查找方式生成 XPath 表达式
        private string GetXPathExpression(string elementType, string namePart, FindMode findMode)
        {
            switch (findMode)
            {
                case FindMode.Contains:
                    return $"//{elementType}[contains(@Name, '{namePart}')]";
                case FindMode.Equals:
                    return $"//{elementType}[@Name='{namePart}']";
                case FindMode.StartsWith:
                    return $"//{elementType}[starts-with(@Name, '{namePart}')]";
                case FindMode.EndsWith:
                    return $"//{elementType}[ends-with(@Name, '{namePart}')]";
                default:
                    throw new ArgumentException("Invalid find mode", nameof(findMode));
            }
        }


        public static AutomationElement GetAddGroupWindow()
        {
            try
            {
                using (var automation = new UIA3Automation())
                {
                    // TXGuiFoundation 添加群
                    IntPtr addWindowHandle = Win32Api.FindWindow("TXGuiFoundation", "添加群");
                    if (addWindowHandle == IntPtr.Zero)
                    {
                        LogManager.Info($"[获取添加聊窗口] 正在寻找:添加群窗口");
                        return null;
                    }
                    return automation.FromHandle(addWindowHandle);
                }
            }
            catch (Exception e)
            {
                LogManager.Error($"[获取添加聊窗口] 获取添加群窗口失败, 原因:{e.Message}");
            }
            return null;
        }


        private static void SetForegroundWindow(AutomationElement window)
        {
            if (window != null && !window.Properties.IsOffscreen.Value)
            {
                IntPtr value = window.Properties.NativeWindowHandle.Value;
                if (!Win32Api.SetForegroundWindow(value))
                {
                    LogManager.Info($"[加群] 置顶窗口失败, handl: {window.Name}");
                }
                LogManager.Info($"[加群] 置顶窗口成功: {window.Name}");
            }
            else
            {
                LogManager.Info("[加群] 置顶窗口失败: 窗口为空或窗口已离屏");
            }
        }



        private static void CloseWindow(AutomationElement window)
        {
            if (window != null)
            {
                try
                {
                    IntPtr hWnd = window.Properties.NativeWindowHandle.Value;
                    if (hWnd != IntPtr.Zero)
                    {
                        LogManager.Info($"[关闭窗口] 成功关闭窗口, 标题:{window.Name} hwnd: {hWnd}");
                        Win32Api.SendMessage(hWnd, Win32Api.WM_CLOSE, IntPtr.Zero, IntPtr.Zero);
                    }
                }
                catch (Exception e)
                {
                    LogManager.Error($"[关闭窗口] 发生异常:", e);
                }
            }
        }

        private static void CloseOtherWindows()
        {
            // 有多个群里会话窗口
            Win32Api.CloseAllQQWindowsEndsWith("个会话");
            // 关闭安全提醒窗口
            // 关闭提示窗口
            // 需要关闭的窗口标题数组
            string[] titles = { "安全提醒", "提示" };
            Win32Api.CloseAllQQWindows(titles);
        }


        /// <summary>
        /// 获取加群进度的qq
        /// </summary>
        /// <returns>qq</returns>
        public string LoadAddGroupProgress()
        {
            if (File.Exists(AddGroupProgressFilePath))
            {
                try
                {
                    return File.ReadAllText(AddGroupProgressFilePath);
                }
                catch (Exception ex)
                {
                    LogManager.Error($"[加载进度] 加载进度文件失败: {ex.Message}");
                }
            }
            return "";
        }

        /// <summary>
        /// 保存加群进度
        /// </summary>
        /// <param name="qq">qq</param>
        public void SaveAddGroudProgress(string qq)
        {
            try
            {
                File.WriteAllText(AddGroupProgressFilePath, qq);
            }
            catch (Exception ex)
            {
                LogManager.Error($"[保存进度] 保存进度文件失败: {ex.Message}");
            }
        }


        public enum FindMode
        {
            Contains,
            Equals,
            StartsWith,
            EndsWith
        }
    }
}
